package com.auth.config;

import com.auth.custom.CustomMd5PasswordEncoder;
import com.auth.filter.TokenAuthenticationFilter;
import com.auth.filter.TokenLoginFilter;
import com.auth.utils.StringPool;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @EnableGlobalMethodSecurity(prePostEnabled = true)
 * 基于方法进行权限校验
 *
 * @Author:Tangjiachang
 * @Date 2023/7/16
 * @Description:
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private final UserDetailsService userDetailService;
    private final CustomMd5PasswordEncoder customMd5PasswordEncoder;
    private final RedisTemplate redisTemplate;
    public WebSecurityConfig(UserDetailsService userDetailService,
                             CustomMd5PasswordEncoder customMd5PasswordEncoder, RedisTemplate redisTemplate) {
        this.customMd5PasswordEncoder = customMd5PasswordEncoder;
        this.userDetailService = userDetailService;
        this.redisTemplate = redisTemplate;
    }

    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .csrf()
                // 关闭csrf跨域请求伪造
                .disable()
                .cors()
                .and()
                .authorizeRequests()
                // 指定某些接口不需要通过验证即可访问
                .antMatchers(StringPool.LOGIN_URL)
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .addFilterBefore(new TokenAuthenticationFilter(redisTemplate),
                        UsernamePasswordAuthenticationFilter.class)
                .addFilter(new TokenLoginFilter(authenticationManager(), redisTemplate));
        // 禁用session
        httpSecurity
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 指定userDetailService和加密器
        auth.userDetailsService(userDetailService)
                .passwordEncoder(customMd5PasswordEncoder);
    }

    /**
     * @Author Tangjiachang
     * @Description  配置哪些请求不拦截
     *               排除swagger相关请求
     * @Date 22:51 2023/7/18
     * @Param [web]
     * @return void
     **/
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
                .antMatchers(StringPool.IGNORE_URL);
    }
}
